/**
 * 
 */
package il.ac.bgu.cs.heuristics.graph.pddl.parser;

import il.ac.bgu.cs.heuristics.graph.Substitution;
import il.ac.bgu.cs.heuristics.graph.pddl.auxiliary.ContradictionResolver;
import il.ac.bgu.cs.heuristics.graph.pddl.parser.types.ITypedConstant;
import il.ac.bgu.cs.heuristics.graph.types.IState;
import il.ac.bgu.cs.heuristics.graph.types.ISubstitution;

import java.io.IOException;
import java.io.InputStream;
import java.util.Set;

import junit.framework.Assert;
import junit.framework.TestCase;

import org.junit.Test;

/**
 * @author haro
 * 
 */
public class StateClassTester extends TestCase {

	public static IState createTestState(ITypedConstant[] constantArray,
			boolean... vars) {
		if (constantArray.length != vars.length)
			throw new IllegalArgumentException(
					"the var and constant array does not match in length");
		ISubstitution[] subs = new Substitution[vars.length];
		try {
			final InputStream in = StateClassTester.class
					.getResourceAsStream(TestUtils.NO_CONTRADICTIONS_FILE_NAME);
			final ContradictionResolver resolver = new ContradictionResolver(in);
			for (int i = 0; i < vars.length; i++) {
				subs[i] = TestUtils.createSubstitution(resolver,
						vars[i] ? TestUtils.IS_TRUE : TestUtils.IS_FALSE,
						constantArray[i]);
			}

		} catch (IllegalArgumentException e) {
			Assert.fail(e.getMessage());
		} catch (IOException e) {
			Assert.fail(e.getMessage());
		}
		return TestUtils.createState(subs);
	}

	@Test
	public void testStateMergeAndOverrideSimpleScenario1() {
		IState stateSource = createTestState(TestUtils.VAR_ARRAY_3, true, true,
				true);
		IState stateDestination = createTestState(TestUtils.VAR_ARRAY_1, false);
		IState ExpectedResult = createTestState(TestUtils.VAR_ARRAY_3, false,
				true, true);

		IState actualResult = stateDestination.mergeAndOverride(stateSource);
		Assert.assertTrue(ExpectedResult.equals(actualResult));
	}

	public void testStateMergeAndOverrideSimpleScenario2() {
		IState stateSource = createTestState(TestUtils.VAR_ARRAY_3, true, true,
				true);
		IState stateDestination = createTestState(TestUtils.VAR_ARRAY_2, false,
				false);
		IState ExpectedResult = createTestState(TestUtils.VAR_ARRAY_3, false,
				false, true);

		IState actualResult = stateDestination.mergeAndOverride(stateSource);
		Assert.assertTrue(ExpectedResult.equals(actualResult));
	}

	public void testStateMergeAndOverrideSimpleScenario3() {
		IState stateSource = createTestState(TestUtils.VAR_ARRAY_1_X3, true);
		IState stateDestination = createTestState(TestUtils.VAR_ARRAY_2, false,
				false);
		IState ExpectedResult = createTestState(TestUtils.VAR_ARRAY_3, false,
				false, true);

		IState actualResult = stateDestination.mergeAndOverride(stateSource);
		Assert.assertTrue(ExpectedResult.equals(actualResult));
	}

	public void testStateClone() {
		IState state1 = createTestState(TestUtils.VAR_ARRAY_2, false, false);
		IState state2 = state1.clone();
		Assert.assertTrue(state1.equals(state2));

	}

	public void testStateSwap() {
		IState state1 = createTestState(TestUtils.VAR_ARRAY_1_X3, true);
		IState state2 = createTestState(TestUtils.VAR_ARRAY_2, false, false);
		Assert.assertFalse(state1.equals(state2));

		IState state1Copy = state1.clone();
		IState state2Copy = state2.clone();
		state1.swap(state2);
		Assert.assertTrue(state1.equals(state2Copy));
		Assert.assertTrue(state2.equals(state1Copy));

	}

	public void testStateContainSubstitution() {
		IState state1 = createTestState(TestUtils.VAR_ARRAY_3, false, false,
				false);
		IState state2 = createTestState(TestUtils.VAR_ARRAY_1, false);
		Set<ISubstitution> subs = state2.getSubstitutions();
		for (ISubstitution sub : subs) {
			Assert.assertTrue(state1.contains(sub));
		}
	}

	public void testStateNotContainSubstitution() {
		IState state1 = createTestState(TestUtils.VAR_ARRAY_2, false, false);
		IState state2 = createTestState(TestUtils.VAR_ARRAY_1_X3, false);
		IState state3 = createTestState(TestUtils.VAR_ARRAY_2, true, true);

		Set<ISubstitution> subs1 = state2.getSubstitutions();
		for (ISubstitution sub : subs1) {
			Assert.assertFalse(state1.contains(sub));
		}

		Set<ISubstitution> subs2 = state3.getSubstitutions();
		for (ISubstitution sub : subs2) {
			Assert.assertFalse(state1.contains(sub));
		}
	}

	public void testStateGetNumberOfContainedSubstitution() {
		IState state1 = createTestState(TestUtils.VAR_ARRAY_2, false, false);
		IState state2 = createTestState(TestUtils.VAR_ARRAY_1_X3, false);
		IState state3 = createTestState(TestUtils.VAR_ARRAY_2, false, false);
		IState state4 = createTestState(TestUtils.VAR_ARRAY_2, false, true);
		Assert.assertEquals(state1.getNumberOfContainedSubstitution(state2
				.getSubstitutions()), 0);
		Assert.assertEquals(state1.getNumberOfContainedSubstitution(state3
				.getSubstitutions()), 2);
		Assert.assertEquals(state1.getNumberOfContainedSubstitution(state4
				.getSubstitutions()), 1);
	}

}
